package com.imooc;

import com.imooc.entity.User;
import com.imooc.util.RedisUtil;
import org.junit.jupiter.api.Test;
import org.redisson.api.RLock;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@SpringBootTest
public class Imooc {

    /**
     * 参考：https://www.zhangshengrong.com/p/zD1yDER2Xr/
     */
    @Test
    public void testRateLimiter() {
        RRateLimiter rateLimiter = RedisUtil.rateLimiter("rate_limiter", RateType.PER_CLIENT, 5, 2);
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            executorService.submit(() -> {
                rateLimiter.acquire();
                System.out.println("线程" + Thread.currentThread().getId() + "进入数据区：" + System.currentTimeMillis());
            });
        }
    }

    @Test
    public void testPublish() {
        User u = new User();
        u.setName("张三");
        u.setAge(12);
        RedisUtil.publish("user", u);
    }

    @Test
    void setCacheObject() {
        User user = new User();
        user.setName("test");
        user.setAge(12);
        RedisUtil.setCacheObject("user", user);
        RedisUtil.setCacheObject("a", "张三");
        RedisUtil.setCacheObject("user2", user, true);
        RedisUtil.setCacheObject("user1", user, 60L);
    }

    @Test
    void testExpire() {
        RedisUtil.expire("user1", 90);
    }

    @Test
    void testGetCacheObject() {
        Object a = RedisUtil.getCacheObject("a");
        System.out.println(a);
    }

    @Test
    void testGetTimeToLive() {
        // key不存在，返回-2
        long a = RedisUtil.getTimeToLive("a");
        System.out.println(a);
    }

    @Test
    void testDeleteObject() {
        Object a = RedisUtil.deleteObject("a");
        System.out.println(a);
    }

    @Test
    void testDeleteByPre() {
        RedisUtil.deleteByPre("s");
    }

    @Test
    void testSetCacheList() {
        List<User> dataList = new ArrayList<>(3);
        User u = new User();
        u.setName("张三");
        u.setAge(123);

        User u1 = new User();
        u1.setName("张三");
        u1.setAge(123);

        dataList.add(u);
        dataList.add(u1);

        RedisUtil.setCacheList("ulist", dataList);
        RedisUtil.setCacheList("ulist2", dataList, 60);
    }

    @Test
    void testDeleteObjects() {
        List<String> s = new ArrayList<>();
        s.add("a");
        s.add("b");
        RedisUtil.deleteObject(s);
    }

    @Test
    void testSetCacheListAdd() {
        User u2 = new User();
        u2.setName("里斯");
        u2.setAge(55);
        RedisUtil.setCacheListAdd("ulist", u2);
    }

    @Test
    void testSetCacheListRemove() {
        User u2 = new User();
        u2.setName("里斯");
        u2.setAge(55);
        RedisUtil.setCacheListRemove("ulist", u2);
    }

    @Test
    void testGetCacheList() {
        System.out.println(RedisUtil.getCacheList("ulist"));
    }

    @Test
    void testSetCacheSet() {
        Set<User> sets = new HashSet<>(2);

        User u = new User();
        u.setName("张三");
        u.setAge(123);

        User u1 = new User();
        u1.setName("张三");
        u1.setAge(123);
        sets.add(u);
        sets.add(u1);
        RedisUtil.setCacheSet("sets", sets);
    }

    @Test
    void testGetCacheSet() {
        System.out.println(RedisUtil.getCacheSet("sets"));
    }

    @Test
    void testSetCacheMap() {
        Map<String, Object> params = new HashMap<>(2);

        User u = new User();
        u.setName("张三");
        u.setAge(123);

        User u1 = new User();
        u1.setName("张三");
        u1.setAge(123);

        params.put("u1", u);
        params.put("u2", u1);

        RedisUtil.setCacheMap("map", params);
    }

    @Test
    void testGetCacheMap() {
        System.out.println(RedisUtil.getCacheMap("map"));
    }

    @Test
    void testSetCacheMapValue() {
        RedisUtil.setCacheMapValue("person", "name", "张三");
        RedisUtil.setCacheMapValue("person", "age", "24");
    }

    @Test
    void testGetCacheMapValue() {
        Object cacheMapValue = RedisUtil.getCacheMapValue("person", "name");
        System.out.println(cacheMapValue);
    }

    @Test
    void testDelCacheMapValue() {
        RedisUtil.delCacheMapValue("person", "name");
    }

    @Test
    void testGetMultiCacheMapValue() {
        Set<String> sets = new HashSet<>(2);
        sets.add("name");
        sets.add("age");
        System.out.println(RedisUtil.getMultiCacheMapValue("person", sets));
    }

    @Test
    void testSetAtomicValue() {
        RedisUtil.setAtomicValue("count", 1);
    }

    @Test
    void testGetAtomicValue() {
        System.out.println(RedisUtil.getAtomicValue("count"));
    }

    @Test
    void testIncrAtomicValue() {
        RedisUtil.incrAtomicValue("count");
    }

    @Test
    void testDecrAtomicValue() {
        RedisUtil.decrAtomicValue("count");
    }

    @Test
    void testKeys() {
        System.out.println(RedisUtil.keys("*u*"));
    }

    @Test
    void testHasKey() {
        System.out.println(RedisUtil.hasKey("count"));
    }

    @Test
    void set() throws InterruptedException {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start("redission休眠看门口狗续约测试");
        final String lockKey = "my_redission_key";
        final RLock lock = RedisUtil.getClient().getLock(lockKey);

        if (lock.tryLock()) {
            try {
                System.out.println("加锁成功，等待观察redis过期时间是否自动续期");

                TimeUnit.SECONDS.sleep(60);

                System.out.println("休眠结束");
            } finally {
                if (lock.isLocked() && lock.isHeldByCurrentThread()) {

                    System.out.println("释放当前执行线程的锁");

                    lock.unlock();
                }
                System.out.println("解锁成功");
            }
        }

        stopWatch.stop();

        System.out.println(stopWatch.prettyPrint());

    }

}
